/*
 Copyright (c) 2013 MeherTJ G. All rights reserved.
 License: LGPL for personnal study or free software.
 */

#pragma once

#include <ctime>
#include <chrono>

namespace Zen
{
    namespace Time
    {
        template <typename TTimeDuration>
        double ToSeconds(TTimeDuration mic)
        {
            return std::chrono::duration<double>(mic).count();
        }

        inline std::chrono::microseconds ToDuration(double seconds)
        {
            using namespace std::chrono;
            microseconds mc((long long)(seconds * microseconds::period::den));
            return mc;
        }

        inline static std::chrono::microseconds Now()
        {
            using namespace std::chrono;
            return duration_cast<microseconds>(system_clock::now().time_since_epoch());
        }
    } // namespace Time

    class Ticker
    {
      public:
        inline Ticker()
        {
            mStartTime = Time::Now();
        }
        std::chrono::microseconds GetDuration() const
        {
            return Time::Now() - mStartTime;
        }
        void Reset()
        {
            mStartTime = Time::Now();
        }
        std::chrono::microseconds Tick() // GetDuration
        {
            auto now = Time::Now();
            auto interval = now - mStartTime;
            mStartTime = now;
            return interval;
        }
        void Delay(std::chrono::microseconds move)
        {
            mStartTime -= move;
        }

      private:
        std::chrono::microseconds mStartTime;
    };

    inline std::function<double /*seconds*/ ()> FunctionUseSeconds(std::function<void()> func)
    {
        auto lamb = [func]() {
            auto start = Zen::Time::Now();
            func();
            auto end = Zen::Time::Now();
            return Zen::Time::ToSeconds(end - start);
        };
        return std::bind(lamb);
    }
} // namespace Zen
